// 简单的 Git 仓库版本
const ora = require('ora').default;
const chalk = require('chalk').default;

// 导入进度条库，用于显示创建进度
// ora 是一个优雅的终端旋转器，可以显示加载状态
// .default 是因为 ora v6+ 使用 ESM 默认导出，在 CommonJS 中需要这样导入

// 导入颜色库，用于美化控制台输出
// chalk 可以为文字添加颜色，让输出更美观
// .default 同样是因为 ESM 兼容性问题

// 预设的在线模板列表
const ONLINE_TEMPLATES = [
  {
    name: 'Vue.js 项目模板',
    value: 'vue',
    url: 'https://github.com/vuejs/vue-cli.git',
    description: 'Vue.js 官方项目模板'
  },
  {
    name: 'React 项目模板',
    value: 'react',
    url: 'https://github.com/facebook/create-react-app.git',
    description: 'React 官方项目模板'
  },
  {
    name: 'Node.js Express 模板',
    value: 'express',
    url: 'https://github.com/expressjs/express.git',
    description: 'Express.js 后端项目模板'
  },
  {
    name: 'TypeScript 项目模板',
    value: 'typescript',
    url: 'https://github.com/microsoft/TypeScript-Node-Starter.git',
    description: 'TypeScript + Node.js 项目模板'
  },
  {
    name: 'Vite + Vue 模板',
    value: 'vite-vue',
    url: 'https://github.com/vitejs/vite.git',
    description: 'Vite + Vue 3 快速开发模板'
  }
];

/**
 * 创建新项目的主函数
 * @param {string} name - 项目名称，来自用户输入
 */
async function create(name) {
  // 动态导入 inquirer 库，用于交互式用户输入
  // 使用 await import() 是因为 inquirer v9+ 是 ESM 模块
  // 在 CommonJS 环境中需要使用动态导入
  const inquirer = await import('inquirer');
  
  // 导入文件系统操作库，提供比原生 fs 更强大的功能
  // fs-extra 是 fs 的超集，添加了很多便利方法
  const fs = require('fs-extra');
  
  // 导入路径处理库，用于处理文件路径
  const path = require('path');

  // 导入子进程模块，用于执行 Git 命令
  const { execSync } = require('child_process');

  // 获取目标目录的绝对路径
  // process.cwd() 返回当前工作目录
  // path.resolve() 将相对路径转换为绝对路径
  const targetDir = path.resolve(process.cwd(), name);

  // 检查目标目录是否已存在
  // 如果目录已存在，显示错误信息并退出函数
  if (fs.existsSync(targetDir)) {
    console.log(chalk.red('目录已存在！'));
    return;
  }

  // 第一步：询问用户选择模板类型
  const { templateType } = await inquirer.default.prompt([
    {
      type: 'list',
      name: 'templateType',
      message: '请选择模板类型：',
      choices: [
        { name: '本地模板 (base)', value: 'local' },
        { name: '在线模板列表', value: 'online' },
        { name: '自定义 Git 仓库', value: 'git' }
      ]
    }
  ]);

  let templateDir;
  let selectedTemplate = null;

  if (templateType === 'online') {
    // 如果选择在线模板列表，显示预设模板
    const { templateName } = await inquirer.default.prompt([
      {
        type: 'list',
        name: 'templateName',
        message: '请选择在线模板：',
        choices: ONLINE_TEMPLATES.map(template => ({
          name: `${template.name} - ${template.description}`,
          value: template.value
        }))
      }
    ]);

    // 获取选中的模板信息
    selectedTemplate = ONLINE_TEMPLATES.find(t => t.value === templateName);
    
    // 第二步：启动进度条
    const spinner = ora(`正在下载 ${selectedTemplate.name}...`).start();

    try {
      // 创建临时目录
      const tempDir = path.resolve(__dirname, '../temp');
      if (fs.existsSync(tempDir)) {
        await fs.remove(tempDir);
      }
      await fs.ensureDir(tempDir);

      // 克隆 Git 仓库到临时目录
      execSync(`git clone ${selectedTemplate.url} ${tempDir}`, { stdio: 'pipe' });
      
      templateDir = tempDir;
      spinner.succeed(`${selectedTemplate.name} 下载成功！`);
    } catch (error) {
      spinner.fail(`${selectedTemplate.name} 下载失败！`);
      console.log(chalk.red('错误信息：'), error.message);
      return;
    }
  } else if (templateType === 'git') {
    // 如果选择自定义 Git 仓库，询问仓库地址
    const { gitUrl } = await inquirer.default.prompt([
      {
        name: 'gitUrl',
        message: '请输入 Git 仓库地址：',
        default: 'https://github.com/username/template-repo.git'
      }
    ]);

    // 第二步：启动进度条
    const spinner = ora('正在从 Git 仓库下载模板...').start();

    try {
      // 创建临时目录
      const tempDir = path.resolve(__dirname, '../temp');
      if (fs.existsSync(tempDir)) {
        await fs.remove(tempDir);
      }
      await fs.ensureDir(tempDir);

      // 克隆 Git 仓库到临时目录
      execSync(`git clone ${gitUrl} ${tempDir}`, { stdio: 'pipe' });
      
      templateDir = tempDir;
      spinner.succeed('模板下载成功！');
    } catch (error) {
      spinner.fail('模板下载失败！');
      console.log(chalk.red('错误信息：'), error.message);
      return;
    }
  } else {
    // 使用本地模板
    templateDir = path.resolve(__dirname, '../templates/base');
  }

  // 第三步：询问用户输入项目描述
  const { desc } = await inquirer.default.prompt([
    { 
      name: 'desc',           // 输入值的变量名
      message: '项目描述',     // 显示的提示文字
      default: ''             // 默认值（空字符串）
    }
  ]);

  // 第四步：启动进度条
  const spinner = ora('正在生成项目...').start();

  try {
    // 第五步：复制模板文件到新项目目录
    await fs.copy(templateDir, targetDir);

    // 第六步：替换模板变量
    await replaceTemplateVariables(targetDir, { name, desc });

    // 第七步：清理临时文件（如果是远程模板）
    if (templateType === 'git' || templateType === 'online') {
      await fs.remove(path.resolve(__dirname, '../temp'));
    }

    // 完成：显示成功信息
    spinner.succeed('项目创建成功！');
    
    // 输出后续操作提示
    console.log(chalk.green(`cd ${name} && npm install`));
    
    // 如果是在线模板，显示额外信息
    if (selectedTemplate) {
      console.log(chalk.blue(`\n📖 模板信息：${selectedTemplate.name}`));
      console.log(chalk.blue(`🔗 模板地址：${selectedTemplate.url}`));
    }
  } catch (error) {
    spinner.fail('项目创建失败！');
    console.log(chalk.red('错误信息：'), error.message);
  }
}

/**
 * 替换模板文件中的变量
 * @param {string} targetDir - 目标目录
 * @param {object} variables - 变量对象
 */
async function replaceTemplateVariables(targetDir, variables) {
  const fs = require('fs-extra');
  const path = require('path');

  // 递归遍历目录中的所有文件
  async function processDirectory(dir) {
    const files = await fs.readdir(dir);
    
    for (const file of files) {
      const filePath = path.join(dir, file);
      const stat = await fs.stat(filePath);
      
      if (stat.isDirectory()) {
        // 如果是目录，递归处理
        await processDirectory(filePath);
      } else {
        // 如果是文件，替换变量
        await processFile(filePath, variables);
      }
    }
  }

  await processDirectory(targetDir);
}

/**
 * 处理单个文件，替换其中的变量
 * @param {string} filePath - 文件路径
 * @param {object} variables - 变量对象
 */
async function processFile(filePath, variables) {
  const fs = require('fs-extra');
  
  // 读取文件内容
  let content = await fs.readFile(filePath, 'utf8');
  
  // 替换变量
  // 将 {{name}} 替换为项目名
  // 将 {{desc}} 替换为项目描述
  content = content.replace(/\{\{name\}\}/g, variables.name);
  content = content.replace(/\{\{desc\}\}/g, variables.desc);
  
  // 写回文件
  await fs.writeFile(filePath, content, 'utf8');
}

// 导出 create 函数，供其他文件使用
module.exports = create;
